package cn.com.doone.common.uc.web.controller;

import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.oltu.oauth2.as.response.OAuthASResponse;
import org.apache.oltu.oauth2.common.error.OAuthError;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import cn.com.doone.common.uc.domain.rs.IRegisterLdapRepository;
import cn.com.doone.common.uc.oauth.OAuthAuthxRequest;
import cn.com.doone.common.uc.oauth.authorize.CodeAuthorizeHandler;
import cn.com.doone.common.uc.oauth.authorize.ExistTokenAuthorizeHandler;
import cn.com.doone.common.uc.oauth.authorize.SMSAuthorizeHandler;
import cn.com.doone.common.uc.oauth.authorize.TokenAuthorizeHandler;
import cn.com.doone.common.uc.oauth.authorize.WeChatAuthorizeHandler;
import cn.com.doone.common.uc.oauth.authorize.WedoAuthorizeHandler;
import cn.com.doone.common.uc.service.IPhoneCodeService;
import cn.com.doone.common.uc.service.dto.PhoneCode;
import cn.com.doone.common.uc.utils.PasswordUtils;
import cn.com.doone.common.uc.utils.PropertiesUtils;
import cn.com.doone.common.uc.utils.SmsUtils;
import cn.com.doone.common.uc.utils.StringUtils;
import cn.com.doone.common.uc.web.WebUtils;
import cn.com.doone.common.uc.web.service.AppService;

/**
 *
 * URL: oauth/authorize
 *
 * @author Shengzhao Li
 */
@Controller
@RequestMapping("oauth/")
public class OauthAuthorizeController {
	
    private static final Logger LOG = LoggerFactory.getLogger(OauthAuthorizeController.class);

    @Autowired
    private PropertiesUtils propertiesUtils;
    
    @Autowired
	private IRegisterLdapRepository registerLdapRepository;
    
    @Autowired
    private IPhoneCodeService phoneCodeService;
    
    @Autowired
    private AppService appService;
    
    /**
     * Must handle the grant_type as follow:
     * grant_type="authorization_code" -> response_type="code"
     * ?response_type=code&scope=read,write&client_id=[client_id]&redirect_uri=[redirect_uri]&state=[state]
     * <p/>
     * grant_type="implicit"   -> response_type="token"
     * ?response_type=token&scope=read,write&client_id=[client_id]&client_secret=[client_secret]&redirect_uri=[redirect_uri]
     * <p/>
     *
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     */
    @RequestMapping("authorize")
    public void authorize(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	
    	SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    	
    	System.out.println("------------------>" + request.getSession().getId());
    	
    	boolean flag = false;
    	try {
            OAuthAuthxRequest oauthRequest = new OAuthAuthxRequest(request);
            
            if (oauthRequest.isCode()) {					// 授权码模式
                CodeAuthorizeHandler codeAuthorizeHandler = new CodeAuthorizeHandler(oauthRequest, response);
   
                LOG.debug("----->登陆处理开始时间：" + df.format(new Date()));
                codeAuthorizeHandler.handle();
                LOG.debug("----->登陆处理结束时间：" + df.format(new Date()));

            } else if (oauthRequest.isToken() && flag) {	// 简单模式-关闭
                TokenAuthorizeHandler tokenAuthorizeHandler = new TokenAuthorizeHandler(oauthRequest, response);
                tokenAuthorizeHandler.handle();

            } else if(oauthRequest.isExistToken()) {		//用已有的token换取code
            	ExistTokenAuthorizeHandler existTokenAuthorizeHandler = new ExistTokenAuthorizeHandler(oauthRequest, response);
            	existTokenAuthorizeHandler.handle();
            } else {
                unsupportResponseType(oauthRequest, response);
            }

        } catch (OAuthProblemException e) {

            OAuthResponse oAuthResponse = OAuthASResponse
                    .errorResponse(HttpServletResponse.SC_FOUND)
                    .location(e.getRedirectUri())
                    .error(e)
                    .buildJSONMessage();
            WebUtils.writeOAuthJsonResponse(response, oAuthResponse);
        }

    }
    
    @RequestMapping("oaRedirectAuth")
    public void appRedirectAuth(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	
    	try {
            OAuthAuthxRequest oauthRequest = new OAuthAuthxRequest(request);
            WedoAuthorizeHandler tokenAuthorizeHandler = new WedoAuthorizeHandler(oauthRequest, response, propertiesUtils);
            LOG.debug("Go to response_type = 'wedo' handler: {}");
            tokenAuthorizeHandler.handle();

        } catch (OAuthProblemException e) {
            //exception
            OAuthResponse oAuthResponse = OAuthASResponse
                    .errorResponse(HttpServletResponse.SC_FOUND)
                    .location(e.getRedirectUri())
                    .error(e)
                    .buildJSONMessage();
            WebUtils.writeOAuthJsonResponse(response, oAuthResponse);
        }

    }
    
    @RequestMapping("wechatRedirectAuth")
    public void wechatRedirectAuth(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	
    	try {
            OAuthAuthxRequest oauthRequest = new OAuthAuthxRequest(request);
            WeChatAuthorizeHandler tokenAuthorizeHandler = new WeChatAuthorizeHandler(oauthRequest, response, propertiesUtils);
            LOG.debug("Go to response_type = 'wedo' handler: {}");
            tokenAuthorizeHandler.handle();

        } catch (OAuthProblemException e) {
            //exception
            OAuthResponse oAuthResponse = OAuthASResponse
                    .errorResponse(HttpServletResponse.SC_FOUND)
                    .location(e.getRedirectUri())
                    .error(e)
                    .buildJSONMessage();
            WebUtils.writeOAuthJsonResponse(response, oAuthResponse);
        }

    }
    
    @RequestMapping("smsRedirectAuth")
    public void smsRedirectAuth(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	
    	try {
            OAuthAuthxRequest oauthRequest = new OAuthAuthxRequest(request);
            SMSAuthorizeHandler tokenAuthorizeHandler = new SMSAuthorizeHandler(oauthRequest, response);
            LOG.debug("Go to response_type = 'SMS' handler: {}");
            tokenAuthorizeHandler.handle();

        } catch (OAuthProblemException e) {
            //exception
            OAuthResponse oAuthResponse = OAuthASResponse
                    .errorResponse(HttpServletResponse.SC_FOUND)
                    .location(e.getRedirectUri())
                    .error(e)
                    .buildJSONMessage();
            WebUtils.writeOAuthJsonResponse(response, oAuthResponse);
        }

    }
    private void unsupportResponseType(OAuthAuthxRequest oauthRequest, HttpServletResponse response) throws OAuthSystemException {
        final String responseType = oauthRequest.getResponseType();
        LOG.debug("Unsupport response_type '{}' by client_id '{}'");

        OAuthResponse oAuthResponse = OAuthResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)
                .setError(OAuthError.CodeResponse.UNSUPPORTED_RESPONSE_TYPE)
                .setErrorDescription("Unsupport response_type '" + responseType + "'")
                .buildJSONMessage();
        WebUtils.writeOAuthJsonResponse(response, oAuthResponse);
    }


    @RequestMapping(value = "oauth_login")
    public String oauthLogin(HttpServletRequest request) {
		String clientId = StringUtils.isNotNull(request.getAttribute("clientId"))?request.getAttribute("clientId").toString():null;
		//根据clientId查询样式文件路径
		Map<String,Object> appMap = appService.queryAppInfoByClientId(clientId);
		if(StringUtils.isNotNull(appMap) && StringUtils.isNotNull(appMap.get("APP_STYLE_URL"))) {
			String appStyleUrl = appMap.get("APP_STYLE_URL").toString();
			request.setAttribute("appStyleUrl", appStyleUrl);
		}else {
			request.setAttribute("appStyleUrl", "/resources/yhzx/css/styles.css");
		}
        return "oauth/oauth_login";
    }


    @RequestMapping(value = "oauth_approval")
    public String oauthApproval() {
        return "oauth/oauth_approval";
    }
    
    @RequestMapping(value = "edit_password")
    public String editPassword(HttpServletRequest request) {
        return "oauth/edit_password";
    }
    
    @RequestMapping(value = "oauth_binding")
    public String oauthBinding() {
        return "oauth/oauth_binding";
    }

	@RequestMapping(value = "sendResetPasswordMessage.action")
	public @ResponseBody Map<String, ? extends Object> sendResetPasswordMessage(HttpServletRequest request) throws Exception {
    	Map<String, Object> map = new HashMap<String, Object>();
		try {
			
			PhoneCode phoneCode = new PhoneCode();
			String userAccount = request.getParameter("userAccount");
			String mobilePhone = request.getParameter("mobilePhone");
			map.put("userAccount", userAccount);
			map.put("mobilePhone", mobilePhone);
			Map<String, Object> paras = phoneCodeService.findUserInfoByAccountAndPhone(map);
			if(paras != null){
				Random random = new Random();
				int code = random.nextInt(899999);
				code = code+100000;
				Calendar cal = Calendar.getInstance();
				cal.add(Calendar.MINUTE,10);
				phoneCode.setCode(code);
				phoneCode.setInvalidTime(cal.getTime());
				phoneCode.setMobilePhone(mobilePhone);
				phoneCode.setUserAccount(userAccount);
				List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
				list = phoneCodeService.findPhoneCodeByAccountAndPhone(map);
				if(list.size() == 0){
					phoneCodeService.insert(phoneCode);
				}else{
					phoneCodeService.updatePhoneCode(phoneCode);
				}
				if(propertiesUtils.isSmsEnable()){
					Map<String,String> smsMap = propertiesUtils.getCodeSmsMap();
					JSONObject smsParamsMap = new JSONObject();
					smsParamsMap.put("code", String.valueOf(code));
					smsMap.put("smsParamString", JSON.toJSONString(smsParamsMap));
					smsMap.put("recNum", mobilePhone);
					SmsUtils.smsSendMessage(smsMap);
				}
				map.put("success", true);
			}else{
				map.put("success", false);
				map.put("message", "账号名或手机号码错误");
				
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			map.put("message", "账号名或手机号码错误");
			map.put("success", false);
		}
		return map;
	}
	
	@RequestMapping(value = "ResetPassword.action")
	public @ResponseBody Map<String, ? extends Object> ResetPassword(HttpServletRequest request) throws Exception {
    	Map<String, Object> map = new HashMap<String, Object>();
		try {
			String userAccount = request.getParameter("userAccount");
			String mobilePhone = request.getParameter("mobilePhone");
			Integer code = Integer.parseInt(request.getParameter("code"));
			map.put("userAccount", userAccount);
			map.put("mobilePhone", mobilePhone);
			map.put("code", code);
			List<Map<String, Object>> list = new ArrayList<Map<String,Object>>(); 
			list = phoneCodeService.searchUserByAccountAndPhone(map);
			if(list.size() > 0){
				String password = RandomStringUtils.randomAlphanumeric(8);
				try {
					map.put("password", PasswordUtils.openLdapMD5(password));
				} catch (NoSuchAlgorithmException e) {
					e.printStackTrace();
				}
				phoneCodeService.updateUserPassword(map);
				
				if (propertiesUtils.isLdapEnable()) {
					String tenantFullName = "OU=Account,dc=doone,dc=com,dc=cn";
					registerLdapRepository.resetPassword(userAccount, tenantFullName,password);
				}
				if(propertiesUtils.isSmsEnable()){
					Map<String,String> smsMap = propertiesUtils.getResetPasswordSmsMap();
					JSONObject smsParamsMap = new JSONObject();
					smsParamsMap.put("password", password);
					smsMap.put("smsParamString", JSON.toJSONString(smsParamsMap));
					smsMap.put("recNum", mobilePhone);
					SmsUtils.smsSendMessage(smsMap);
				}
				map.put("success", true);
			}else{
				map.put("success", false);
				map.put("message", "账号名、手机号码或验证码错误");
				
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			map.put("message", "账号名、手机号码或验证码错误");
			map.put("success", false);
		}
		return map;
	}

}